"""
图形用户界面模块
使用 tkinter 构建 GUI
"""
import tkinter as tk
from tkinter import ttk, filedialog, messagebox, scrolledtext
import threading
import os
from .config import ConfigManager
from .sync_engine import SyncEngine
from .realtime import FileMonitor


class SyncToolGUI:
    """同步工具GUI"""
    
    def __init__(self, root):
        self.root = root
        self.root.title("文件盘同步工具")
        self.root.geometry("1000x700")
        
        # 配置管理器
        self.config_manager = ConfigManager()
        
        # 运行中的同步任务
        self.running_tasks = {}  # {task_id: {"engine": SyncEngine, "monitor": FileMonitor, "thread": Thread}}
        
        # 创建UI
        self._create_ui()
        
        # 加载任务列表
        self._load_tasks()
    
    def _create_ui(self):
        """创建用户界面"""
        # 顶部工具栏
        toolbar = ttk.Frame(self.root)
        toolbar.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5)
        
        ttk.Button(toolbar, text="➕ 添加任务", command=self._add_task).pack(side=tk.LEFT, padx=2)
        ttk.Button(toolbar, text="✏️ 编辑任务", command=self._edit_task).pack(side=tk.LEFT, padx=2)
        ttk.Button(toolbar, text="🗑️ 删除任务", command=self._delete_task).pack(side=tk.LEFT, padx=2)
        ttk.Separator(toolbar, orient=tk.VERTICAL).pack(side=tk.LEFT, fill=tk.Y, padx=5)
        ttk.Button(toolbar, text="▶️ 开始同步", command=self._start_sync).pack(side=tk.LEFT, padx=2)
        ttk.Button(toolbar, text="⏸️ 停止同步", command=self._stop_sync).pack(side=tk.LEFT, padx=2)
        ttk.Separator(toolbar, orient=tk.VERTICAL).pack(side=tk.LEFT, fill=tk.Y, padx=5)
        ttk.Button(toolbar, text="🔄 完整同步", command=self._full_sync).pack(side=tk.LEFT, padx=2)
        ttk.Button(toolbar, text="⚙️ 设置", command=self._show_settings).pack(side=tk.LEFT, padx=2)
        
        # 主分割窗口
        paned = ttk.PanedWindow(self.root, orient=tk.VERTICAL)
        paned.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 任务列表区域
        task_frame = ttk.LabelFrame(paned, text="同步任务列表", padding=10)
        paned.add(task_frame, weight=3)
        
        # 创建表格
        columns = ("ID", "名称", "源目录", "文件进度", "状态", "模式")
        self.task_tree = ttk.Treeview(task_frame, columns=columns, show="headings", height=10)
        
        # 设置列
        self.task_tree.heading("ID", text="ID")
        self.task_tree.heading("名称", text="任务名称")
        self.task_tree.heading("源目录", text="源目录")
        self.task_tree.heading("文件进度", text="文件进度")
        self.task_tree.heading("状态", text="状态")
        self.task_tree.heading("模式", text="同步模式")
        
        self.task_tree.column("ID", width=50)
        self.task_tree.column("名称", width=150)
        self.task_tree.column("源目录", width=300)
        self.task_tree.column("文件进度", width=120)
        self.task_tree.column("状态", width=80)
        self.task_tree.column("模式", width=100)
        
        # 滚动条
        scrollbar = ttk.Scrollbar(task_frame, orient=tk.VERTICAL, command=self.task_tree.yview)
        self.task_tree.configure(yscrollcommand=scrollbar.set)
        
        self.task_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 日志区域
        log_frame = ttk.LabelFrame(paned, text="同步日志", padding=10)
        paned.add(log_frame, weight=2)
        
        self.log_text = scrolledtext.ScrolledText(log_frame, height=15, wrap=tk.WORD)
        self.log_text.pack(fill=tk.BOTH, expand=True)
        
        # 状态栏
        self.status_bar = ttk.Label(self.root, text="就绪", relief=tk.SUNKEN)
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
    
    def _load_tasks(self):
        """加载任务列表"""
        # 保存当前选中项
        selected_ids = []
        for item in self.task_tree.selection():
            values = self.task_tree.item(item)["values"]
            if values:
                selected_ids.append(values[0])  # values[0] 是 ID
        
        # 清空现有项
        for item in self.task_tree.get_children():
            self.task_tree.delete(item)
        
        # 加载任务
        tasks = self.config_manager.get_tasks()
        for task in tasks:
            status = "运行中" if task["id"] in self.running_tasks else "已停止"
            mode = "双向" if task.get("bidirectional", False) else "单向"
            
            # 显示文件进度
            total_files = task.get("total_files", 0)
            synced_files = task.get("synced_files", 0)
            if total_files > 0:
                file_progress = f"{synced_files}/{total_files}"
            else:
                file_progress = "-/-"
            
            item_id = self.task_tree.insert("", tk.END, values=(
                task["id"],
                task.get("name", "未命名"),
                task["source_dir"],
                file_progress,
        status,
                mode
            ))
            
            # 恢复选中状态
            if task["id"] in selected_ids:
                self.task_tree.selection_add(item_id)
    
    def _add_task(self):
        """添加新任务"""
        dialog = TaskDialog(self.root, self.config_manager)
        if dialog.result:
            self._load_tasks()
            self._log("任务添加成功")
    
    def _edit_task(self):
        """编辑任务"""
        selected = self.task_tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要编辑的任务")
            return
        
        task_id = int(self.task_tree.item(selected[0])["values"][0])
        
        # 如果任务正在运行，不允许编辑
        if task_id in self.running_tasks:
            messagebox.showwarning("警告", "请先停止任务再编辑")
            return
        
        task = self.config_manager.get_task(task_id)
        dialog = TaskDialog(self.root, self.config_manager, task)
        if dialog.result:
            self._load_tasks()
            self._log("任务更新成功")
    
    def _delete_task(self):
        """删除任务"""
        selected = self.task_tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要删除的任务")
            return
        
        task_id = int(self.task_tree.item(selected[0])["values"][0])
        
        # 如果任务正在运行，先停止
        if task_id in self.running_tasks:
            messagebox.showwarning("警告", "请先停止任务再删除")
            return
        
        if messagebox.askyesno("确认", "确定要删除此任务吗？"):
            self.config_manager.delete_task(task_id)
            self._load_tasks()
            self._log(f"任务 #{task_id} 已删除")
    
    def _start_sync(self):
        """开始实时同步"""
        selected = self.task_tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要启动的任务")
            return
        
        task_id = int(self.task_tree.item(selected[0])["values"][0])
        
        if task_id in self.running_tasks:
            messagebox.showinfo("提示", "任务已在运行中")
            return
        
        task = self.config_manager.get_task(task_id)
        if not task:
            messagebox.showerror("错误", "任务不存在")
            return
        
        # 检查目录是否存在
        if not os.path.exists(task["source_dir"]):
            messagebox.showerror("错误", f"源目录不存在: {task['source_dir']}")
            return
        
        try:
            # 创建同步引擎
            settings = self.config_manager.get_settings()
            
            # 定义进度回调
            def update_progress(total, synced):
                # 只有在任务仍在运行时才更新
                if task_id not in self.running_tasks:
                    return
                # 更新任务的文件统计
                for t in self.config_manager.config.tasks:
                    if t.id == task_id:
                        t.total_files = total
                        t.synced_files = synced
                        break
                # 在UI线程中刷新界面
                self.root.after(0, self._load_tasks)
            
            engine = SyncEngine(
                source_dir=task["source_dir"],
                target_dirs=task["target_dirs"],
                ignore_patterns=settings["ignore_patterns"],
                bidirectional=task.get("bidirectional", False),
                callback=self._log,
                progress_callback=update_progress
            )
            
            # 创建文件监控
            monitor = FileMonitor(engine, callback=self._log)
            
            # 先执行一次完整同步（在后台线程）
            def initial_sync():
                engine.full_sync()
                if engine.running or task_id in self.running_tasks:
                    monitor.start()
            
            sync_thread = threading.Thread(target=initial_sync, daemon=True)
            sync_thread.start()
            
            # 保存到运行中的任务
            self.running_tasks[task_id] = {
                "engine": engine,
                "monitor": monitor,
                "thread": sync_thread
            }
            
            self._load_tasks()
            self._log(f"任务 #{task_id} [{task.get('name', '未命名')}] 已启动")
            self.status_bar.config(text=f"运行中: {len(self.running_tasks)} 个任务")
            
        except Exception as e:
            messagebox.showerror("错误", f"启动任务失败: {e}")
            self._log(f"启动任务失败: {e}", "ERROR")
    
    def _stop_sync(self):
        """停止同步"""
        selected = self.task_tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要停止的任务")
            return
        
        task_id = int(self.task_tree.item(selected[0])["values"][0])
        
        if task_id not in self.running_tasks:
            messagebox.showinfo("提示", "任务未在运行")
            return
        
        try:
            task_info = self.running_tasks[task_id]
            task_info["monitor"].stop()
            task_info["engine"].stop()
            
            del self.running_tasks[task_id]
            
            self._load_tasks()
            self._log(f"任务 #{task_id} 已停止")
            self.status_bar.config(text=f"运行中: {len(self.running_tasks)} 个任务")
            
        except Exception as e:
            messagebox.showerror("错误", f"停止任务失败: {e}")
    
    def _full_sync(self):
        """执行完整同步（一次性）"""
        selected = self.task_tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要同步的任务")
            return
        
        task_id = int(self.task_tree.item(selected[0])["values"][0])
        task = self.config_manager.get_task(task_id)
        
        if not task:
            messagebox.showerror("错误", "任务不存在")
            return
        
        if task_id in self.running_tasks:
            messagebox.showwarning("警告", "任务正在运行中，无需手动同步")
            return
        
        try:
            settings = self.config_manager.get_settings()
            
            # 定义进度回调
            def update_progress(total, synced):
                # 只有在任务仍在运行时才更新
                if task_id not in self.running_tasks:
                    return
                # 更新任务的文件统计
                for t in self.config_manager.config.tasks:
                    if t.id == task_id:
                        t.total_files = total
                        t.synced_files = synced
                        break
                # 在UI线程中刷新界面
                self.root.after(0, self._load_tasks)
            
            engine = SyncEngine(
                source_dir=task["source_dir"],
                target_dirs=task["target_dirs"],
                ignore_patterns=settings["ignore_patterns"],
                bidirectional=task.get("bidirectional", False),
                callback=self._log,
                progress_callback=update_progress
            )
            
            # 在后台线程执行
            def run_sync():
                engine.full_sync()
                self._log(f"任务 #{task_id} 完整同步完成")
            
            thread = threading.Thread(target=run_sync, daemon=True)
            thread.start()
            
            self._log(f"开始执行任务 #{task_id} 的完整同步...")
            
        except Exception as e:
            messagebox.showerror("错误", f"执行同步失败: {e}")
    
    def _show_settings(self):
        """显示设置对话框"""
        SettingsDialog(self.root, self.config_manager)
    
    def _log(self, message: str, level: str = "INFO"):
        """添加日志"""
        import datetime
        timestamp = datetime.datetime.now().strftime("%H:%M:%S")
        log_line = f"[{timestamp}] [{level}] {message}\n"
        
        self.log_text.insert(tk.END, log_line)
        self.log_text.see(tk.END)
        
        # 限制日志行数
        lines = int(self.log_text.index('end-1c').split('.')[0])
        if lines > 1000:
            self.log_text.delete('1.0', '100.0')
    
    def on_closing(self):
        """关闭窗口时的处理"""
        if self.running_tasks:
            if messagebox.askyesno("确认", "有任务正在运行，确定要退出吗？"):
                # 停止所有任务
                for task_id in list(self.running_tasks.keys()):
                    task_info = self.running_tasks[task_id]
                    task_info["monitor"].stop()
                    task_info["engine"].stop()
                self.root.destroy()
        else:
            self.root.destroy()


class TaskDialog:
    """任务编辑对话框"""
    
    def __init__(self, parent, config_manager, task=None):
        self.result = None
        self.config_manager = config_manager
        self.task = task
        self.target_dirs = task["target_dirs"].copy() if task else []
        
        # 创建对话框
        self.dialog = tk.Toplevel(parent)
        self.dialog.title("编辑任务" if task else "添加任务")
        self.dialog.geometry("600x500")
        self.dialog.transient(parent)
        self.dialog.grab_set()
        
        self._create_ui()
        
        # 如果是编辑模式，填充现有数据
        if task:
            self._load_task_data()
        
        # 等待对话框关闭
        self.dialog.wait_window()
    
    def _create_ui(self):
        """创建UI"""
        main_frame = ttk.Frame(self.dialog, padding=10)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 任务名称
        ttk.Label(main_frame, text="任务名称:").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.name_entry = ttk.Entry(main_frame, width=50)
        self.name_entry.grid(row=0, column=1, sticky=tk.W, pady=5)
        
        # 源目录
        ttk.Label(main_frame, text="源目录 (主盘):").grid(row=1, column=0, sticky=tk.W, pady=5)
        source_frame = ttk.Frame(main_frame)
        source_frame.grid(row=1, column=1, sticky=tk.W, pady=5)
        self.source_entry = ttk.Entry(source_frame, width=42)
        self.source_entry.pack(side=tk.LEFT)
        ttk.Button(source_frame, text="浏览", command=self._browse_source).pack(side=tk.LEFT, padx=5)
        
        # 目标目录列表
        ttk.Label(main_frame, text="目标目录:").grid(row=2, column=0, sticky=tk.NW, pady=5)
        target_frame = ttk.Frame(main_frame)
        target_frame.grid(row=2, column=1, sticky=tk.W, pady=5)
        
        list_frame = ttk.Frame(target_frame)
        list_frame.pack(fill=tk.BOTH, expand=True)
        
        self.target_listbox = tk.Listbox(list_frame, height=8, width=50)
        self.target_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.target_listbox.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.target_listbox.config(yscrollcommand=scrollbar.set)
        
        btn_frame = ttk.Frame(target_frame)
        btn_frame.pack(fill=tk.X, pady=5)
        ttk.Button(btn_frame, text="添加目录", command=self._add_target_dir).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_frame, text="删除选中", command=self._remove_target_dir).pack(side=tk.LEFT, padx=2)
        
        # 同步模式
        ttk.Label(main_frame, text="同步模式:").grid(row=3, column=0, sticky=tk.W, pady=5)
        self.mode_var = tk.StringVar(value="单向")
        mode_frame = ttk.Frame(main_frame)
        mode_frame.grid(row=3, column=1, sticky=tk.W, pady=5)
        ttk.Radiobutton(mode_frame, text="单向同步", variable=self.mode_var, value="单向").pack(side=tk.LEFT)
        ttk.Radiobutton(mode_frame, text="双向同步", variable=self.mode_var, value="双向").pack(side=tk.LEFT, padx=10)
        
        # 按钮
        btn_frame = ttk.Frame(main_frame)
        btn_frame.grid(row=4, column=0, columnspan=2, pady=20)
        ttk.Button(btn_frame, text="保存", command=self._save).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="取消", command=self.dialog.destroy).pack(side=tk.LEFT, padx=5)
    
    def _load_task_data(self):
        """加载任务数据"""
        self.name_entry.insert(0, self.task.get("name", ""))
        self.source_entry.insert(0, self.task["source_dir"])
        
        for target_dir in self.task["target_dirs"]:
            self.target_listbox.insert(tk.END, target_dir)
        
        self.mode_var.set("双向" if self.task.get("bidirectional", False) else "单向")
    
    def _browse_source(self):
        """浏览源目录"""
        directory = filedialog.askdirectory(title="选择源目录")
        if directory:
            self.source_entry.delete(0, tk.END)
            self.source_entry.insert(0, directory)
    
    def _add_target_dir(self):
        """添加目标目录"""
        directory = filedialog.askdirectory(title="选择目标目录")
        if directory:
            if directory not in self.target_dirs:
                self.target_dirs.append(directory)
                self.target_listbox.insert(tk.END, directory)
    
    def _remove_target_dir(self):
        """删除目标目录"""
        selected = self.target_listbox.curselection()
        if selected:
            index = selected[0]
            self.target_listbox.delete(index)
            self.target_dirs.pop(index)
    
    def _save(self):
        """保存任务"""
        name = self.name_entry.get().strip()
        source_dir = self.source_entry.get().strip()
        
        if not name:
            messagebox.showwarning("警告", "请输入任务名称")
            return
        
        if not source_dir or not os.path.exists(source_dir):
            messagebox.showwarning("警告", "请选择有效的源目录")
            return
        
        if not self.target_dirs:
            messagebox.showwarning("警告", "请至少添加一个目标目录")
            return
        
        task_data = {
            "name": name,
            "source_dir": source_dir,
            "target_dirs": self.target_dirs,
            "bidirectional": self.mode_var.get() == "双向"
        }
        
        if self.task:
            # 更新任务
            self.config_manager.update_task(self.task["id"], task_data)
        else:
            # 添加新任务
            self.config_manager.add_task(task_data)
        
        self.result = task_data
        self.dialog.destroy()


class SettingsDialog:
    """设置对话框"""
    
    def __init__(self, parent, config_manager):
        self.config_manager = config_manager
        
        self.dialog = tk.Toplevel(parent)
        self.dialog.title("设置")
        self.dialog.geometry("500x400")
        self.dialog.transient(parent)
        self.dialog.grab_set()
        
        self._create_ui()
        self._load_settings()
        
        self.dialog.wait_window()

    def _create_ui(self):
        """创建UI"""
        main_frame = ttk.Frame(self.dialog, padding=10)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 忽略模式
        ttk.Label(main_frame, text="忽略模式 (每行一个):").pack(anchor=tk.W, pady=5)
        self.ignore_text = scrolledtext.ScrolledText(main_frame, height=15, width=60)
        self.ignore_text.pack(fill=tk.BOTH, expand=True, pady=5)
        
        # 按钮
        btn_frame = ttk.Frame(main_frame)
        btn_frame.pack(pady=10)
        ttk.Button(btn_frame, text="保存", command=self._save).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="取消", command=self.dialog.destroy).pack(side=tk.LEFT, padx=5)
    
    def _load_settings(self):
        """加载设置"""
        settings = self.config_manager.get_settings()
        ignore_patterns = settings.get("ignore_patterns", [])
        self.ignore_text.insert('1.0', '\n'.join(ignore_patterns))
    
    def _save(self):
        """保存设置"""
        settings = self.config_manager.get_settings()
        
        # 获取忽略模式
        ignore_text = self.ignore_text.get('1.0', tk.END).strip()
        ignore_patterns = [line.strip() for line in ignore_text.split('\n') if line.strip()]
        settings["ignore_patterns"] = ignore_patterns
        
        self.config_manager.update_settings(settings)
        messagebox.showinfo("成功", "设置已保存")
        self.dialog.destroy()

